/**
  ***********************************************************************************
  * @file   : Service_Communication.cpp
  * @brief  : Communication support file.This file provides access ports to interface
  *           with connected devices.
  ***********************************************************************************
                                 ##### Port List #####
  =================================================================================
  |Port Name     Physical-Layer     Data-Link-Layer    Application-Layer    Number
  |————————————————————————————————————————
  |EXAMPLE_Port       CAN1               CAN                CUSTOM            0
  |CAN2_Port          CAN2               CAN                Custom            1
  |EBUG_Port         USART1             Custom              Custom            2
  |USART2_Port       USART2              DBUS               DJI-DR16          3
  *
**/
/* Includes ------------------------------------------------------------------*/
#include "Service_Communication.h"
#include "Service_Devices.h"
#include <string.h>
/* Private define ------------------------------------------------------------*/
void Task_UsartRecieve(void *arg);
void Task_UsartTransmit(void *arg);
void Task_CAN1Transmit(void *arg);
void Task_CAN1Receive(void *arg);

/**
* @brief  Initialization of communication service
* @param  None.
* @return None.
*/
void Service_Communication_Init(void)
{
  /* CAN Filter Config*/
  CAN_Filter_Mask_Config(&hcan1, CanFilter_14|CanFifo_0|Can_STDID|Can_DataType,0x200,0x000);//筛选器:|编号|FIFOx|ID类型|帧类型|ID|屏蔽位(0x3ff,0x1FFFFFFF)|

  xTaskCreate(Task_UsartRecieve,	"Com.Usart RxPort" , 	Small_Stack_Size,    		NULL, PriorityHigh,   			&UsartRxPort_Handle);
  xTaskCreate(Task_UsartTransmit,	"Com.Usart TxPort" , 	Small_Stack_Size,    		NULL, PriorityHigh,   			&UsartTxPort_Handle);  
	xTaskCreate(Task_CAN1Receive,		"Com.CAN1 RxPort" , 	Normal_Stack_Size,    	NULL, PriorityHigh,   			&CAN1RxPort_Handle);
	xTaskCreate(Task_CAN1Transmit,	"Com.CAN1 TxPort" , 	Normal_Stack_Size,    	NULL, PriorityHigh,   			&CAN1TxPort_Handle);
}

/*----------------------------------------------- CAN Manager ---------------------------------------------*/
/*Task Define ---------------------------*/
TaskHandle_t CAN1TxPort_Handle;
TaskHandle_t CAN1RxPort_Handle;

static void Convert_Data(CAN_RxMessage* input, CAN_COB* output);


/*Function Prototypes--------------------*/
void Task_CAN1Transmit(void *arg)
{
  /* Cache for Task */
//  uint8_t free_can_mailbox;
	CAN_COB CAN_TxMsg;
	
  /* Pre-Load for task */
  
  /* Infinite loop */
  for(;;)
  {
    /* CAN1 Send Port */
    if(xQueueReceive(CAN1_TxPort,&CAN_TxMsg,portMAX_DELAY) == pdPASS)
    {
      CANx_SendData(&hcan1,CAN_TxMsg.ID,CAN_TxMsg.Data,CAN_TxMsg.DLC);		
    }
  }
}


void Task_CAN1Receive(void *arg)
{
  /* Cache for Task */
  CAN_COB CAN_RxMsg;
	
  /* Pre-Load for task */
  
  /* Infinite loop */
  
  for(;;)
  {
    /* CAN1 Receive Port */
    if(xQueueReceive(CAN1_RxPort,&CAN_RxMsg,portMAX_DELAY) == pdPASS)
    {		
			/* 更新电机数据 */
			if(motor.CheckID(CAN_RxMsg.ID))
			{
				motor.update(CAN_RxMsg.Data);			
			}
    }
  }
}

/**
* @brief  Callback function in CAN Interrupt
* @param  None.
* @return None.
*/
void CAN1_CallBack(CAN_RxBuffer *CAN_RxMessage)
{
  static CAN_COB   CAN_RxCOB;
  Convert_Data(CAN_RxMessage,&CAN_RxCOB);
  //Send To CAN Receive Queue
  if(CAN1_RxPort != NULL)
    xQueueSendFromISR(CAN1_RxPort,&CAN_RxCOB,0);
}

/**
* @brief  Data convertion，provide lower layer access port 
          for application layer.
* @param  CAN_RxMsg：Lower layer CAN frame.
          CAN_RxCOB：Application layer CAN Frame.
* @return None.
*/
static void Convert_Data(CAN_RxMessage* input, CAN_COB* output)
{
  output->ID = input->header.StdId;
  output->DLC = input->header.DLC;
  memcpy(output->Data, input->data, output->DLC);
}

/*---------------------------------------------- USART Manager --------------------------------------------*/
/*Task Define ---------------------------*/
TaskHandle_t UsartRxPort_Handle;
TaskHandle_t UsartTxPort_Handle;

/*Function Prototypes--------------------*/
/**
* @brief  Tasks for USART Management.
          Attention:In this version we passing the pointer of data not copying
          data itself and we only have one buff zone, so user need to process 
          the data as soon as possible in case of over-write.
* @param  None.
* @return None.
*/

/**
 *@brief 串口接收
 */ 
void Task_UsartRecieve(void *arg)
{
	USART_COB Usart_RxCOB;
	
	for(;;)
  {
    /* Usart Recevice Port */ 
		if(xQueueReceive(USART_RxPort,&Usart_RxCOB,portMAX_DELAY) == pdPASS)
    {
	
    }
  }
}

/**
 *@brief 串口发送
 */ 
void Task_UsartTransmit(void *arg)
{
	USART_COB Usart_TxCOB;
	for(;;)
  {
    /* Usart Transmit Port */ 
		if(xQueueReceive(USART_TxPort,&Usart_TxCOB,portMAX_DELAY) == pdPASS)
    {

    }
  }
}

uint32_t User_UART2_RxCpltCallback(uint8_t* Recv_Data, uint16_t ReceiveLen)
{
  static USART_COB Usart_RxCOB;
  //Send To UART Receive Queue
  if(USART_RxPort != NULL)
  {
    Usart_RxCOB.port_num = 2;
    Usart_RxCOB.len      = ReceiveLen;
    Usart_RxCOB.address  = Recv_Data;
    xQueueSendFromISR(USART_RxPort,&Usart_RxCOB,0);
  }
  return 0;
}




/************************ COPYRIGHT(C) SCUT-ROBOTLAB **************************/
